SANA-II Network Device Driver Specification November 7, 1991 Draft for Final Comments and Approval Dale Larson, Greg Miller Amiga Networking Group, New Siberia Office Introduction The SANA-II Network Device Driver Specification is a standard for the interface to any Amiga networking hardware. It is a specification for an Amiga software interface to the data link layer in the ISO 7-Layer Reference Model of Open Systems Interconnection. All Amiga network hardware vendors should supply a SANA-II device driver for their hardware. All protocol writers should talk to SANA-II device drivers rather than to network hardware. Any protocol stack should work with any SANA-II device driver. The standard has been kept simple and straight-forward so that SANA-II device drivers should be easy to write and to use. They should be highly efficient and have low resource usage. Any SANA-II device driver should behave very much like any other SANA-II device driver. Application writers must not use SANA-II Device Drivers directly. Applications must use the API provided by the network protocol software the application supports. It is hoped that a standard network API for all Amigas will be made available by Commodore in the near future. This version of the standard addresses issues from the original SANA-II standard which were raised in the 1991 North American and European Amiga DevCons as well as in the conversion of existing protocols to the use of the standard. This draft reflects several rounds of comments from active implementors of SANA-II software. Most of the changes are simplifications and should be easy to incorporate into any work in progress. The changes should make the writing and use of SANA-II drivers much easier. Commodore's internal versions of the A2065 and other drivers and the AS225 software package are currently compliant with this version of the SANA-II spec. This version of the specification is very solid and will stand as final unless comments containing very compelling objections are received by December 31, 1991. All SANA-II device drivers and software utilizing those drivers should be written to this version of the specification. Distribution of this version of the standard is unlimited. Comments should be emailed to dlarson@cmbvax.commodore.com or sent to Dale Larson, Software Engineer, Commodore, 1200 Wilson Drive, West Chester, PA 19380, USA. Changes Most changes are explained in detail below, but for those already familiar with the 1991 DevCon draft of the SANA-II standard, here is a summary list of the important points: - Packet type specification has been drastically simplified. Protocols no longer specify any framing information -- packet magic is eliminated and a convention is adopted for handling the framing problem faced by ethernet drivers. - NetBuffs are removed from the standard and replaced with a function callback. - Station aliasing has been eliminated from the standard. - Since the IOSana2Req structure had to be changed anyway, many names in have been changed to be more consistent with other system names. It is believed that global search and replace should make this a mostly trivial change and that the benefits gained from consistent naming outweigh the inconvenience to those few who have existing SANA-II code. - Events are now defined as a bit mask rather than as scalars. Acknowledgements Many people and companies have contributed to the SANA-II Network Device Driver Specification. The original SANA-II autodocs and includes were put together by Ray Brand, Perry Kivolowitz (ASDG) and Martin Hunt. Those original documents evolved to their current state and grew to include this document at the hands of Dale Larson and Greg Miller. Randell Jesup has provided sage advice on several occasions and the buffer management callback mechanism was his idea. Dale Luck (GfxBase) and Rick Spanbauer (Ameristar Technologies) have provided valuable comments throughout the process. Nicolas Benezan (ADONIS) provided many very detailed and useful comments on weaknesses in late drafts of the specification. Thanks to all the above and the numerous others who have contributed with their comments, questions and discussions. Unresolved Issues Unfortunately, it isn't possible to completely isolate network protocols from the hardware they run on. Hardware types and addressing both remain somewhat hardware-dependent in spite of our efforts. See the "Packet Type" section for an explanation of how packet types are handled and why protocols cannot be isolated from them. See the "Addressing" section for an explanation of how addressing is handled any why protocols cannot be isolated from it. Finally, some protocol standards are simply very hardware specific. They have particular issues which can't be dealt with from a general data link layer specification designed to isolate protocols from hardware. For example, TCP/IP RFC 1201 cannot be implemented without a special hardware driver. The impact of such issues should be negligible for most protocols running on most hardware, and the issues won't be made significantly more difficult to address by virtue of existence the SANA-II standard. Driver Form SANA-II device drivers are Amiga Exec device drivers. They have an extended IORequest structure and a number of extended commands for network statistics, broadcast/multicast, addressing and unexpected packets. The Amiga ROM Kernel Reference Manual: Devices includes information on how to construct an Exec device. We plan to release source to an example SANA-II device driver in the near future. Buffer Management Most Exec device drivers read and write contiguous blocks of data and keep internal buffers. Networking software is very good at physically fragmenting a logical block of data with headers and trailers as well as requiring dynamically tunable buffers. To allow the efficient implementation of networking protocols therefore requires a non-contiguous physical data structure with a buffering scheme which is easily externally tunable. The original SANA-II device driver specification therefore called for drivers to have no internal buffers and to get all buffers from protocols in the form of a data structure called a NetBuff. Hence, all protocols were required to use NetBuffs. This was highly unsatisfactory since most protocols are implemented from an existing code base which includes its own buffer management scheme. To solve this problem, the standard has been revised so that drivers still have no internal buffers, but now they read and write to and from an abstract data structure via calls to functions provided by the protocol. The protocol must provide two functions -- one to copy data to the abstract data structure and one to copy data from the abstract data structure. The protocol can therefore use it's choice of data structure for buffer management and allow this to be used by the driver in order to have very efficient memory and CPU usage overall. The Sana2IOReq contains a pointer to data and the length of the data pointed to, but a driver is allowed to make no assumptions about how the data is stored and therefore cannot directly manipulate or examine the buffer in any manner whatsoever other than by calling the protocol-provided functions. At OpenDevice() a protocol points ios2_BufferManagment to a list of tags which include pointers to the functions required by the driver. The driver makes sure that all required functions are supplied and fails the open if they are not. If the open is successful, the driver points ios2_BufferManagement to a magic cookie which it uses from then on to access these functions. The driver could in theory choose to just copy the taglist to driver-owned memory and then to parse the list for every IORequest, but it is much more efficient for the driver to create some sort of table of functions and to point ios2_BufferManagement to that table. The specification currently includes only two tags for the OpenDevice() ios2_BufferManagement taglist: S2_CopyToBuff - This is a pointer to a function which conforms to the CopyToBuff autodoc. S2_CopyFromBuff - This is a pointer to a function which conforms to the CopyFromBuff autodoc. Opening a SANA-II Device As when opening any other Exec device, on the call to OpenDevice() a SANA-II device is passed an IORequest structure to initialize for use by the opener. This structure is copied by the opener if it desires to use multiple async requests. The SANA-II IORequest is defined as follows: struct IOSana2Req { struct IORequest ios2_Req; ULONG ios2_WireError; ULONG ios2_PacketType; UBYTE ios2_SrcAddr[SANA2_MAX_ADDR_BYTES]; UBYTE ios2_DstAddr[SANA2_MAX_ADDR_BYTES]; ULONG ios2_DataLength; void *ios2_Data; void *ios2_StatData; void *ios2_BufferManagement; }; ios2_Req A standard Exec device IORequest. WireError A more specific device code which may be set when there is an io_Error. PacketType The type of packet requested. SrcAddr The device fills in this field with the interface address of the source of the packet that satisfied a read command. The bytes used to hold the address will be left justified but the bit layout is dependent on the particular type of network. DstAddr This field is filled in with the interface destination address of the packet for a send command. The bytes used to hold the address will be left justified but the bit layout is dependent on the particular type of network. DataLength The requestor fills this field with the amount of data available in the buffer. The device fills in this field with the size of the packet data as it was sent on the wire. This does not include the header and trailer information. Depending on the network type and protocol type, the driver may have to calculate this value. This is generally used only for reads and writes (including broadcast and multicast). Data A pointer to some abstract data structure containing packet data. Drivers may not directly manipulate or examine anything pointed to by Data! This pointer is generally used only for reads and writes (including broadcast and multicast). StatData Pointer to a data area in memory to place a snapshot of device statistics. The data area must be long word aligned. This pointer is only used on calls to the statistics commands. BufferManagement A pointer to a taglist when OpenDevice() is called. Functions pointed to in the taglist are called by the device when processing IORequests from the opener. When returned from OpenDevice(), this field contains a pointer to driver private information used to access these functions. The flags used with the device on OpenDevice() are (SANA2OPB_xxx): MINE Exclusive access to the unit requested. PROM Promiscuous mode requested. The flags used during I/O requests are (SANA2IOB_xxx): RAW Raw packet read/write requested. BCAST Broadcast packet (received). MCAST Multicast packet (received). QUICK Quick IO requested. Packet Type Network frames always have a type field associated with them. These type fields vary in length, position and meaning by frame type (frames types generally correspond one-to-one with hardware types, but see "Ethernet Packet Types" below.). The meaning of the type numbers are always carefully defined and every type number is registered with some official body. You must not use a type number which is not registered with the governing body for the standard hardware you are accessing. Basically, this means that if you want to write a new protocol (rather than implementing an existing one), you've got a lot of paperwork ahead of you. This is one of the reasons why applications cannot be written directly on top of SANA-II device drivers. The type field allows the SANA-II device driver to fulfill CMD_READs based on the type of packet the protocol wants. Multiple protocols can therefore run over the same wire using the same driver without stepping on each other's toes. Packet types are now specified simply as a long word. No current hardware uses more than a long word type and it is at all likely that a longer type field would be adapted for use in a common hardware frame within the lifetime of this standard. Furthermore, if such a problem ever did arise, it is certainly the case that there wouldn't be more than a longword of types in use and we could provide some kind of mapping in the drivers for such a wire. Unfortunately, the type field means different things on different wires. Protocol writers must allow their protocol to be configurable with a SANA-II device name, unit number and the type number(s) used by the protocol stack with this device. This way if new hardware becomes available, the manufacturer-supplied listing of type assignments can be used to configure the protocol. Ethernet Packet Types Ethernet has a special problem with packet types. Two types of ethernet frames can be sent over the same wire -- ethernet and 802.3. These frames differ in that the Type field of an ethernet frame is the Length field of an 802.3 frame. This creates a problem in that demultiplexing incoming packets can be cumbersome and inefficient, as well as requiring protocol writers to be aware of the frame type used. The original standard called for a generalized "Packet Magic" which all drivers and protocols had to deal with, even though few people should ever have to worry about the problem. We could also have specified that there are 802.3 SANA-II drivers and that there are ethernet drivers and that if you want 802.3 and ethernet (even if on the same wire) from the same machine, use two ethernet boards. This didn't make sense because we don't anticipate multiple protocols needing to use 802.3 frames nor much encouragement for hardware manufactures to provide special 802.3 drivers. The current solution keeps the standard simple and allows highly efficient implementations, but it does make ethernet drivers a little more complex and does make using 802.3 frames harder. SANA-II ethernet drivers return packets contained in ethernet frames normally when the requested Type does not fall within the 802.3 range (all and only 802.3 frames have numbers less than 1500 in the type field). If a Type within the 802.3 range is requested, the driver returns the next packet contained within an 802.3 frame, regardless of the type of the packet within the 802.3 frame. This requires that there be no more than one requestor of 802.3 packets and that it do it's own interpretation of the frames. Addressing Network hardware addresses are stored under the SANA-II standard in an array of n bytes. No meaning is ascribed to the contents of the array by the standard. We know of no network which does not have an address field consisting of a number of bits not divisible by eight. In case one exists, however, any padding necessary because the number of significant bits in an address is not evenly divisible by eight belongs at the end of the bit stream. For example, if an address is ten bits long it will be stored like this: 98765432 10PPPPPP BYTE 0 BYTE 1 Where the numerals are bit numbers and 'P' is a pad (ignored) bit. Protocols which choose not to implement the bit shifting necessary to use a network with such addressing (should one exist) should at least check the number of significant bits in the address field (returned from S2_DEVICEQUERY) to make sure that it is evenly divisible by eight. Protocols will map hardware addresses to protocol addresses in a protocol and hardware dependent manner. Some protocols will always use the same mapping on all hardware, but other protocols will have particular address mapping schemes for some particular hardware and a reasonable default for other (unknown) hardware. Some SANA-II devices will have "hardware addresses" which aren't really hardware addresses. As an example, consider PPP. PPP (Point-to-Point Protocol) is a standard for transmitting packets over a serial line. It uses IP addresses as "hardware addresses." The specific address to be used is negotiated during the establishment of a connection. Thus, the address in SrcAddr returned from S2_CONFIGINTERFACE (or in a subsequent S2_GETSTATIONADDRESS) from a PPP driver will be the length of an IP address and will only be valid after the device has been configured. Note that some hardware always uses a ROM hardware address, while other hardware which has a ROM address or is configurable with DIP switches may be overriden by software and that some hardware always dynamically allocates a new hardware address at initialization. See Configuration for details on how this is handled. Station Aliases The original standard called for an interface to the ability of some hardware to simultaneously accept packets for several hardware addresses. Such a feature is of dubious usefulness. In order to simplify the standard, station aliases are no longer part of the SANA-II Network Device Driver Specification. If station aliasing does turn out to be a useful feature available on some hardware for the Amiga, the standard can easily be extended to re-introduce station aliasing. Remember that all Exec drivers must check for io_Command values not supported by the driver. Hence, SANA-II commands can be added without requiring that existing drivers be rev'd. Hardware Type The HardwareType returned by S2_DEVICEQUERY is necessary for those protocols whose standards require different behavior on different hardware and for determining appropriate packet type numbers to use with the device. The HardwareType values already issued for standard network hardware are the same as those in RFC 1060 (assigned numbers). If you are a hardware developer with a new type of network, contact CATS to have a hardware type number assigned to you and added to the SANA-II includes. Protocols should all have reasonable defaults for hardware with which they are not familiar. Errors The SANA-II extended IORequest structure (struct IOSana2Req) includes both the ios2_Error and ios2_WireError fields. IOSana2Reqs returned to the requester must always be checked for an error in ios2_Error. ios2_Error will be zero if no error occurred, else it will contain a value from or from . If there was an error, there may be more specific information in ios2_WireError. Drivers are required to fill in the WireError if there is an applicable error code. Error codes are #defined in the "defined errors" sections of : IOSana2Req S2io_Error field (S2ERR_xxx): NO_RESOURCES Insufficient resources available. BAD_ARGUMENT Noticeably bad argument. BAD_STATE Command inappropriate for current state. BAD_ADDRESS Noticably bad address. MTU_EXCEEDED Write data too large. NOT_SUPPORTED Command is not supported by this driver. This is similar to IOERR_NOCMD as defined in but S2ERR_NOT_SUPPORTED indicates that the requested command is a valid SANA-II command and that the driver does not support it because the hardware is incapable of supporting it (e.g., S2_MULTICAST). Note that IOERR_NOCMD is still valid for reasons other than a lack of hardware support (i.e., commands which are no-ops in a SANA-II driver). SOFTWARE Software error of some kind. OUTOFSERVICE When a protocol is taken offline, any pending requests are returned with this error. SEE ALSO the standard errors in . IOSana2Req S2io_WireError field (S2WERR_xxx): NOT_CONFIGURED Command requires unit to be configured. UNIT_ONLINE Command requires that the unit be offline. UNIT_OFFLINE Command requires that the unit be online. ALREADY_TRACKED Protocol is already being tracked. NOT_TRACKED Protocol is not being tracked. BUFF_ERROR Buffer management function error return caused error. SRC_ADDRESS Problem with the source address field. DST_ADDRESS Problem with destination address field. BAD_BROADCAST Problem with an attempt to broadcast. BAD_MULTICAST Problem with an attempt to multicast. ALIAS_LIST_FULL Station alias list full. BAD_ALIAS Bad or unknown station alias. MULTICAST_FULL Multicast address list full. BAD_EVENT Event specified is unknown. BAD_STATDATA The S2IO_StatData pointer or the data it points to failed a sanity check. IS_CONFIGURED Attempt to reconfigure the unit. NULL_POINTER A NULL pointer was detected in one of the arguments. S2ERR_BAD_ARGUMENT should always be the S2ERR. Standard Commands See the autodocs for full details on each of the Exec device standard and SANA-II device extended commands. Extended commands are explained in the sections below. Many of the Exec device standard commands are no-ops in SANA-II devices, but some of these might become used in the future depending on the needs of new hardware for which SANA-II devices are implemented. For example, CMD_RESET might someday be used for dynamically reconfiguring hardware on which this is useful. This should present no compatibility problems. Broadcast and Multicast S2_ADDMULTICASTADDRESS S2_DELMULTICASTADDRESS S2_MULTICAST S2_BROADCAST Some hardware supports broadcast and/or multicast. A broadcast is a packet which is sent to all other machines. A multicast is a packet which is sent to a set of machines. Drivers for hardware which does not allow broadcast or multicast will return ios2_Error S2ERR_NOT_SUPPORTED on an attempt to use an inappropriate function. To send a broadcast, just use S2_BROADCAST instead of CMD_WRITE. Broadcasts are received just like any other packets, with a CMD_READ for the appropriate packet type. To send a multicast, just use S2_MULTICAST instead of CMD_WRITE. To receive a multicast, the multicast address to be listened on must be added with S2_ADDMULTICASTADDRESS and then a CMD_READ must be placed for the type of packet to be received. Some SANA-II devices which support multicast may have a limited number of multicast addresses which can be listened on simultaneously so you must thus check for S2WERR_MULTICAST_FULL when adding a multicast address. Note that when a multicast address is added, it is usually added for all users of the device, not just the protocol which called S2_ADDMULTICASTADDRESS. In other words, if packets of a type you are requesting are multicast to an address for which S2_ADDMULTICAST has been called, you will receive these packets even if you didn't add any multicast addresses. In general, when you receive a packet, you should not care how the packet was sent, only that it got to you. If you really want to know, however, you can check for SANA2IOB_BCAST and/or SANA2IOB_MCAST in the ios2_Flags field. Drivers should keep a count for the number of opens on a multicast address so that they don't actually remove it until it has been S2_DELMULTICASTADDRESS'd as many times as it has been S2_ADDMULTICASTADDRESS'd Stats S2_TRACKTYPE S2_UNTRACKTYPE S2_GETTYPESTATS S2_GETSPECIALSTATS S2_GETGLOBALSTATS S2_READORPHAN There are many statistics which may be very important to the protocol writer trying to debug, optimize and tune an implementation as well as to the end user who may need to tune parameters or investigate a problem. Some of these statistics can only be kept by the SANA-II driver, and there are thus many required and optional statistics and commands to get at these. S2_TRACKTYPE tells the device driver to gather statistics for a particular packet type. S2_UNTRACKTYPE tells it to stop (keeping statistics by type causes the driver to use additional resources). S2_GETTYPESTATS returns any statistics accumulated by the driver for a type being tracked (stats are lost when a type is S2_UNTRACKTYPE'd). Drivers are required to implement the functionality of type tracking. The stats are returned in a struct Sana2PacketTypeStats: struct Sana2PacketTypeStats { ULONG PacketsSent; ULONG PacketsReceived; ULONG BytesSent; ULONG BytesReceived; ULONG PacketsDropped; }; PacketsSent Number of packets of a particular type sent. PacketsReceived Number of packets of a particular type that satisfied a read command. BytesSent Number of bytes of data sent in packets of a particular type. BytesReceived Number of bytes of data of a particular packet type that satisfied a read command. PacketsDropped Number of packets of a particular type that were received while there were no pending reads of that packet type. S2_GETGLOBALSTATS returns global statistics kept by the driver. Drivers are required to keep all applicable statistics, and most drivers will therefore keep all of them. The stats are returned in a struct Sana2DeviceStats: struct Sana2DeviceStats { ULONG PacketsReceived; ULONG PacketsSent; ULONG BadData; ULONG Overruns; ULONG UnknownTypesReceived; ULONG Reconfigurations; struct timeval LastStart; }; PacketsReceived Number of packets that this unit has received. PacketsSent Number of packets that this unit has sent. BadData Number of bad packets received (i.e., hardware CRC failed). Overruns Number of packets dropped due to insufficient resources available in the network interface. UnknownTypeReceived Number of packets received that had no pending read command with the appropriate packet type. Reconfigurations Number of network reconfigurations since this unit was last configured. LastStart The time when this unit last went online. S2_GETSPECIALSTATS returns any special statistics kept by a particular driver. It is hoped that each wire type will have a set of documented required statistics for that wire type and a standard set of optional statistics for that wire type (optional because they might not be available from all hardware). The data returned by S2_GETSPECIALSTATS will require wire-specific interpretation, see for currently defined special statistics. The statistics are returned in the following structures: struct Sana2SpecialStatRecord { ULONG Type; ULONG Count; char *String; }; Type Statistic identifier. Count Statistic itself. String Identifying string for the statistic. Should be plain ASCII with no formatting characters. struct Sana2SpecialStatHeader { ULONG RecordCountMax; ULONG RecordCountSupplied; struct Sana2SpecialStatRecord[RecordCountMax]; }; RecordCountMax Space for this many number of records is available to place statistics information in. RecordCountSupplied Number of statistic records supplied. S2_READORPHAN is not, strictly speaking, a statistical function. It is a request to read any packet of a type for which there is no outstanding CMD_READ. S2_READORPHAN might be used in the same manner as many statistics, though, such as to determine what packet types are causing overruns, etc. Configuration S2_DEVICEQUERY S2_GETSTATIONADDRESS S2_CONFIGINTERFACE Network hardware needs to be configured before it is used. Some parameters about the hardware must be known by protocol software (hardware address and MTU, for example) when it is used. These commands address those needs. When a network protocol is started, it should try to S2_CONFIGINTERFACE even though an interface can only be configured once and someone else may have done it. In order to properly S2_CONFIGINTERFACE, you must first S2_GETSTATIONADDRESS to determine the factory address (if any). You must also provide for user-override of the factory address (that address may be optional and the user may need to override it). When S2_CONFIGINTERFACE returns, you must check the ios2_SrcAddr for the actual address the hardware has been configured with. This is because some hardware (or serial line standards such as PPP) always dynamically allocates an address at initialization. Protocol writers will want to use S2_DEVICEQUERY to determine the MTU and other characteristics of the network. The structure returned from S2_DEVICEQUERY is defined as: struct Sana2DeviceQuery { ULONG SizeAvailable; ULONG SizeSupplied; ULONG DevQueryFormat; ULONG DeviceLevel; UWORD AddrFieldSize; ULONG MTU; ULONG BPS; ULONG HardwareType; }; SizeAvailable Size, in bytes, of the space available in which to place device information. This includes both size fields. SizeSupplied Size, in bytes, of the data supplied. DevQueryFormat The format defined here is format 0. DeviceLevel This spec defines level 0. AddrFieldSize The number of bits in an interface address. MTU Maximum Transmission Unit, the size, in bytes, of the maximum packet size, not including header and trailer information. BPS Best guess at the raw line rate for this network in bits per second. HardwareType Specifies the type of network hardware the driver controls. Online S2_ONLINE S2_OFFLINE S2_ONEVENT In order to allow hardware tests to be run on an otherwise live system, the S2_OFFLINE command allows the SANA-II device driver to be "turned off" until the tests are complete and an ONLINE is sent to the driver. S2_ONLINE causes the interface will be re- configured and re-initialized, and any packets destined for the hardware while the device was offline will have been lost. All pending and new requests to the driver should be returned with S2ERR_OUTOFSERVICE when a device is offline. All protocol software must understand that any IO request may be returned with S2ERR_OUTOFSERVICE because the driver has been taken offline. In such an event, the protocol will usually want to wait until the unit comes back S2_ONLINE. It may do this by calling S2_ONEVENT to wait for S2EVENT_ONLINE. S2_ONEVENT allows various events for the driver to be waited on. Events usually happen in multiples. A driver must track events, but may not distinguish between some types of events. If an event is not tracked, an S2_ONEVENT for the event is returned with S2_ERR_NOT SUPPORTED and S2WERR_BAD_EVENT. Errors which seem caused by a malformed or unusual request should not generally trigger an event. Event types (S2EVENT_xxx): ERROR Return when any error occurs. TX Return on any transmit error. (Always an Error.) RX Return on any receive error. (Always an Error.) ONLINE Return when unit goes online or return immediately if unit is already online. (Not an Error.) OFFLINE Return when unit goes offline or return immediately if unit is already offline. (Not an Error.) BUFF Return on any buffer management function error. (Always an Error.) HARDWARE Return when any hardware error occurs. (Always an Error, may be a TX or RX, too.) SOFTWARE Return when any software error occurs. (Always an Error, may be a TX or RX, too.)